home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / utility3 / bc_cdk.zip / CDK_BC.TXT
Text File  |  1991-09-01  |  23KB  |  578 lines

  1.  
  2.  
  3.  
  4.                              Using Borland C++ IDE with 
  5.                the Microsoft Visual BASIC Control Development Kit (CDK)
  6.  
  7.  
  8.  
  9.           I wrote this description to help anyone using Borland's C++
  10.           compiler and Integrated Development Environment (IDE) to create
  11.           custom controls for use with Microsoft's Visual BASIC.  The MS
  12.           CDK (Control Development Kit) has a series of example programs
  13.           that were written to work with Microsoft C version 6 or later. 
  14.           This document should help you get them to work using Borland's
  15.           development products.
  16.  
  17.           This document assumes that you have purchased the MS CDK product. 
  18.           I make reference to specific line numbers within the files that
  19.           were shipped to me with version 1.0 of that product.  When
  20.           working with Borland's IDE, you can tell what line that you are
  21.           currently editing by referencing the numbers in the bottom left-
  22.           hand corner of the active edit window.  The numbers shown there
  23.           appear in the format:
  24.  
  25.                           <line number> : <column position>
  26.  
  27.           for example:
  28.                                         25:32
  29.  
  30.           which says that your cursor is on the 32nd character of line 25.
  31.  
  32.           In this document, I also assume that you have installed your
  33.           Borland C++ product in the drive\subdirectory C:\BORLANDC.  Also
  34.           that after installing the CDK, you have copied the file VBAPI.LIB
  35.           to C:\BORLANDC\LIB and the file VBAPI.H to C:\BORLANDC\INCLUDE.
  36.  
  37.           While experimenting with this code, I created a subdirectory
  38.           called TEMP under the directory for each control, copied all
  39.           files for that control there, and edited the copies.  It is NEVER
  40.           advisable to edit your original copies of anything.  Also
  41.           remember that whenever you are coding at a systems-level, you
  42.           should save your code frequently.
  43.  
  44.           If you have any comments, suggestions, or neat VBX files, please
  45.           feel free to drop me a line in my Compuserve mailbox, or at my
  46.           humble homestead at 1188 Morgan Ave, Williamsport, PA 17701.
  47.  
  48.           Throughout this document, I mention products and programs that
  49.           are protected by some sort of legal nonsense or another, and I
  50.           hope I can appease all legal-eagles by saying that any Borland
  51.           product mentioned is trademarked and legally protected by Borland
  52.           International Inc. of Scotts Valley, CA.  Any Microsoft product
  53.           is trademarked and legally protected by Microsoft Corporation of
  54.           Redmond, WA.  Anything done by you using the descriptions here
  55.           should make neither them (nor me) liable for any silliness that
  56.           might prevail.
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.           Brent K. Langley  Compuserve Userid 70312,2142             Page 1
  66.  
  67.  
  68.                              Using Borland C++ IDE with 
  69.                the Microsoft Visual BASIC Control Development Kit (CDK)
  70.  
  71.  
  72.  
  73.           GETTING THE CDK TO WORK:
  74.  
  75.           I have found that in getting the CDK code to work with the IDE
  76.           there are 8 steps that I had to follow:
  77.  
  78.           1)   Change WINDOWS.H
  79.           2)   Copy and Rename LibInit.Obj to C:\BORLANDC\LIB\C0VBINIT.OBJ 
  80.           3)   Create a Project file (.PRJ) to create the VBX/DLL file
  81.           4)   Change CCINIT.C to take advantage of changes in WINDOWS.H
  82.           5)   Handle any syntax errors in demo code
  83.           6)   Handle any language incompatibilities in code
  84.           7)   "Make" Project from IDE
  85.           8)   Rename (or Copy) xxxxxxxx.DLL to xxxxxxxx.VBX
  86.  
  87.           Steps 1 and 2 from above only need to be done once.  Steps 3 and
  88.           4 need to be done for every project, but follow the same steps. 
  89.           Steps 5 and 6 will be addressed separatly for each of the three
  90.           example programs that need fixing.  Steps 7 and 8 let you put all
  91.           of the pieces together. 
  92.  
  93.           STEP ONE:  CHANGE WINDOWS.H
  94.  
  95.           The normal startup code for a DLL does a little processing and
  96.           then calls your function called LibMain.  In a .VBX file, we have
  97.           to replace the normal startup code with a modified routine that
  98.           passes some extra information to our control's LibMain.  This
  99.           means that the format for calling a VBX's LibMain is different
  100.           from a normal DLL's LibMain.  This causes no real hassle to
  101.           MSC/SDK developers because Microsoft doesn't include a function
  102.           prototype in their version of WINDOWS.H for LibMain, however,
  103.           Borland does.  And when Borland's compiler sees the CDK version
  104.           of the LibMain function, it stops compiling with an error.
  105.  
  106.           We could just remove the function prototype for LibMain from
  107.           Borland's WINDOWS.H, but it will help us with our syntax checking
  108.           if we leave it there.  My solution is to define a constant called
  109.           _CDK before the #include of WINDOWS.H.  Then have WINDOWS.H
  110.           determine the existance of this defined constant to decide
  111.           whether to use the CDK or normal version of LibMain.
  112.  
  113.           To do this, load C:\BORLANDC\INCLUDE\WINDOWS.H and then press
  114.           Ctrl-PgDn to go to the bottom of the file.  Move your cursor up
  115.           to about line 3473, and you should see Borland's function
  116.           prototype for LibMain.  I changed this part of the code to be:
  117.  
  118.           #ifndef  _CDK
  119.           int FAR PASCAL LibMain ( HANDLE, WORD, WORD, LPSTR );
  120.           #else
  121.           BOOL FAR PASCAL LibMain( HANDLE, HANDLE, unsigned short );
  122.           #endif
  123.  
  124.           I used "unsigned short" instead of USHORT for the third parameter
  125.           of the CDK version of LibMain because USHORT isn't seen in a
  126.           typedef statement until the file VBAPI.H is #include'd later.
  127.  
  128.  
  129.           Brent K. Langley  Compuserve Userid 70312,2142             Page 2
  130.  
  131.  
  132.                              Using Borland C++ IDE with 
  133.                the Microsoft Visual BASIC Control Development Kit (CDK)
  134.  
  135.  
  136.  
  137.           STEP TWO:  RENAME LIBINIT.OBJ TO C0VBINIT.OBJ
  138.  
  139.           Page 20 of the CDK Guide explains that LIBINIT.OBJ contains
  140.           initialization code to replace the code from the file
  141.           LIBENTRY.OBJ that is normally linked into DLL projects first.  So
  142.           we must ensure that the code from LIBINIT.OBJ is linked before
  143.           any other code in our projects.
  144.  
  145.           On page 141 of Borland's C++ User Guide, we find the section of
  146.           the project manager chapter titled "Overriding Libraries" states
  147.           that we can have our own startup file linked first, if:
  148.  
  149.                1)   its name starts with C0 (the letter C followed by zero)
  150.                2)   it is placed as the first file in the project.
  151.  
  152.           We'll worry about making a project file in a minute, but for now,
  153.           lets give LibInit.OBJ a new name to conform with step one from
  154.           above.  While we're at it, lets also move it to a standard
  155.           location (since the CDK manual says that this code would seldom
  156.           need to change.)  If LibInit.OBJ is in your current directory,
  157.           type:
  158.  
  159.                     COPY LIBINIT.OBJ  C:\BORLANDC\LIB\C0VBINIT.OBJ
  160.  
  161.           You could call it anything you want (so long as it starts with
  162.           "C0") but since it contains the Visual Basic INITialization code,
  163.           I thought that this name was appropriate.
  164.  
  165.           STEP THREE:  CREATE A PROJECT FILE
  166.  
  167.           For each control, you will make a project file that looks similar
  168.           to the following:
  169.  
  170.                               C:\BORLANDC\LIB\C0VBINIT.OBJ
  171.                               C:\BORLANDC\LIB\C0DC.OBJ
  172.                               C:\BORLANDC\LIB\VBAPI.LIB
  173.                               CCINIT.C
  174.                               program.DEF
  175.                               program.RC
  176.                               program.C
  177.                               .
  178.                               . (any other program files or libraries)
  179.                               .
  180.  
  181.           For example, the project for the CNTR control would look like:
  182.  
  183.                               C:\BORLANDC\LIB\C0VBINIT.OBJ
  184.                               C:\BORLANDC\LIB\C0DC.OBJ
  185.                               C:\BORLANDC\LIB\VBAPI.LIB
  186.                               CCINIT.C
  187.                               CNTR.DEF
  188.                               CNTR.RC
  189.                               CNTR.C
  190.  
  191.  
  192.  
  193.           Brent K. Langley  Compuserve Userid 70312,2142             Page 3
  194.  
  195.  
  196.                              Using Borland C++ IDE with 
  197.                the Microsoft Visual BASIC Control Development Kit (CDK)
  198.  
  199.  
  200.  
  201.           STEP THREE: CREATE A PROJECT FILE (continued)
  202.  
  203.           The file C:\BORLANDC\LIB\C0DC.OBJ listed in the above projects is
  204.           the normal startup code file for Borland C (that has been
  205.           superseded by C0VBINIT.OBJ) and should appear immediately after
  206.           C0VBINIT.OBJ in your project file.  This file should actually be
  207.           C0Dx.OBJ where "x" indicates your memory model that you are
  208.           compiling with.  Since I used the "Compact" memory model for
  209.           compiling my projects, this is C0Dc.OBJ in my code examples.
  210.  
  211.           Since a VBX file is a type of DLL, you should let the project
  212.           manager know that you will be creating a DLL.  You can do this by
  213.           typing Alt-O to activate the Options menu.  Type A to select your
  214.           Application type, and then type D to select DLL.  Now when you
  215.           save your project, this information will be stored with it.
  216.  
  217.           Besides the interactive way of building a project, you could make
  218.           a batch file to create your project files, or you could copy this
  219.           text to a .PRJ file, but then remember to run PRJCNVT to change
  220.           the old-style text project file to Borland's new project file
  221.           format.  
  222.  
  223.           An example .BAT file called MAKEPRJ.BAT might contain:
  224.  
  225.                     @ECHO OFF
  226.                     IF "%1"=="" GOTO ERROR
  227.                     ECHO C:\BORLANDC\LIB\C0VBINIT.OBJ > %1.PRJ
  228.                     ECHO C:\BORLANDC\LIB\C0DC.OBJ    >> %1.PRJ
  229.                     ECHO C:\BORLANDC\LIB\VBAPI.LIB   >> %1.PRJ
  230.                     ECHO CCINIT.C                    >> %1.PRJ 
  231.                     ECHO %1.DEF                      >> %1.PRJ
  232.                     ECHO %1.RC                       >> %1.PRJ
  233.                     ECHO %1.C                        >> %1.PRJ
  234.                     PRJCNVT %1.PRJ  
  235.                     GOTO END
  236.                     :ERROR
  237.                     ECHO You must specify a project name
  238.                     :END
  239.  
  240.           This uses the program PRJCNVT.EXE in your C:\BORLANDC\BIN
  241.           subdirectory (probably in you PATH) to convert from a text .PRJ
  242.           file to Borland's new project file format.  The first ECHO
  243.           statement creates a new .PRJ file, and the rest of the ECHO
  244.           statements append their line of text to this file.  The file is
  245.           named using whatever you specify on the command line after the
  246.           word MAKEPRJ.  For Example:
  247.  
  248.                                     MAKEPRJ  CNTR
  249.  
  250.           Would make the project example shown on the previous page and
  251.           name it CNTR.PRJ.  Remember then to set the Alt-O-A-D options
  252.           when you load this into the IDE.
  253.  
  254.  
  255.  
  256.  
  257.           Brent K. Langley  Compuserve Userid 70312,2142             Page 4
  258.  
  259.  
  260.                              Using Borland C++ IDE with 
  261.                the Microsoft Visual BASIC Control Development Kit (CDK)
  262.  
  263.  
  264.  
  265.           STEP FOUR:  CHANGE CCINIT.C
  266.  
  267.           In step one, we modified WINDOWS.H to allow correct function
  268.           prototyping of the LibMain function.  In the file CCINIT.C we
  269.           will take advantage of this change.  This is the file where our
  270.           version of LibMain is declared, so we want WINDOWS.H to use the
  271.           CDK version of the prototype.
  272.  
  273.           This is pretty simple, all you need to do is to include the line:
  274.  
  275.                                     #define _CDK 
  276.  
  277.           before the #include <windows.h> statement in the file CCINIT.C.  
  278.  
  279.           I suggest that you type over line 6 in this file which is
  280.           currently blank.  This will preserve the line numbers for the
  281.           rest of the code.  CCINIT.C is very similar for each of the
  282.           example programs in the CDK, but each does vary slightly.  Please
  283.           make this change for every sample control project in the CDK.
  284.  
  285.           STEP FIVE:  HANDLE SYNTAX ERRORS
  286.           STEP SIX:  HANDLE ANY LANGUAGE INCOMPATIBILITIES
  287.  
  288.           CIRCLE1, CIRCLE2, and PUSH have no further problems so you can
  289.           continue with steps seven and eight for them.  
  290.  
  291.           However, there is still some work that needs to be done with the
  292.           files for CIRCLE3, CNTR, and PIX.  I prefer to address the
  293.           problems for each of these programs separately, so please see
  294.           their individual descriptions on the following pages.
  295.  
  296.  
  297.           STEP SEVEN:  MAKE PROJECT
  298.  
  299.           You're just about done!  Press F9 and the IDE will create your
  300.           DLL file.  If you prefer to use Borland's MAKE utility, you can
  301.           convert your .PRJ file from step three (above) to a .MAK file
  302.           with the Borland utility PRJ2MAK and then edit this make file to
  303.           tailor it to your own specifications.
  304.  
  305.           STEP EIGHT:  RENAME .DLL FILE TO .VBX
  306.  
  307.           The IDE's project manager will create a file with the same
  308.           filename as that of your .PRJ file.  The resulting file's
  309.           extension will be .DLL but the Visual BASIC system will be
  310.           expecting a Visual Basic eXtension file.  To accomodate Visual
  311.           BASIC, just RENAME (I prefer to COPY)  name.DLL to name.VBX
  312.  
  313.           That's all there is (as if it isn't enough!)  Now you can load
  314.           Visual BASIC and select Alt F D  for File Add-file and specify
  315.           your .VBX file.
  316.  
  317.  
  318.  
  319.  
  320.  
  321.           Brent K. Langley  Compuserve Userid 70312,2142             Page 5
  322.  
  323.  
  324.                              Using Borland C++ IDE with 
  325.                the Microsoft Visual BASIC Control Development Kit (CDK)
  326.  
  327.  
  328.  
  329.                                        CIRCLE3
  330.  
  331.           In addition to following the steps described above (such as
  332.           putting the #define _CDK in CCINIT.C) CIRCLE3 has some
  333.           compatibility problems:
  334.  
  335.           CIRCLE3 PROBLEM 1:
  336.  
  337.           On line 114 of CIRCLE.C there is a call to VBCreateHsz that uses
  338.           the new MS C v6 type keyword "_segment".  My info on this keyword
  339.           comes from an article in the March 1990 issue of Microsoft
  340.           Systems Journal by Noel J. Bergman.  While describing the new (at
  341.           that time) version 6 of MS C, he describes briefly, on page 58,
  342.           the concept of "based pointers" and the function of _segement.  
  343.  
  344.           He says: "When _segment is used to cast a near address, the
  345.           result is the current value in DS" which can be obtained in BC++
  346.           by specifying _DS or FP_SEG( (void far *) addr ).   He continues:
  347.           "If the address is a far address, the result is the segment for
  348.           that far address."  You can use the FP_SEG( addr ) macro in dos.h
  349.           to get this value.
  350.  
  351.           A consistent way to handle both cases would be to use the FP_SEG
  352.           macro and cast (void far *) on the pointer.  For example:
  353.  
  354.                              FP_SEG( (void far *) addr ) 
  355.  
  356.           Or, since the macro does this casting for you internally, you can
  357.           abbreviate this as just: 
  358.                                     FP_SEG( addr )
  359.  
  360.           A side note:  when looking in the include file dos.h I found that
  361.           FP_SEG is using a cast operation with the word _seg !?!   What is
  362.           that?? Is it the same as _segment ??  It doesn't seem so.  Since
  363.           I couldn't find it in the documentation, lets play it safe and
  364.           stick with FP_SEG.  Although, if you are converting a MAJOR
  365.           project, you could speed up the conversion by doing a global
  366.           search and replace:  changing all 
  367.  
  368.                                       (_segment)
  369.           to 
  370.                              (void _seg *)(void far *)  
  371.  
  372.  
  373.           Using FP_SEG is easier to read (I think), and a little more
  374.           portable.  The choice is up to you, but for this example, lets
  375.           change line 114 of CIRCLE.C to read:     
  376.  
  377.                      hsz = VBCreateHsz( FP_SEG(hctl), (LPSTR)lp);
  378.  
  379.           and then put the #include <dos.h> on the blank line between the
  380.           includes for <windows.h> and <vbapi.h>  (this will preserve line
  381.           numbers for the further editing that we have to do...)
  382.  
  383.  
  384.  
  385.           Brent K. Langley  Compuserve Userid 70312,2142             Page 6
  386.  
  387.  
  388.                              Using Borland C++ IDE with 
  389.                the Microsoft Visual BASIC Control Development Kit (CDK)
  390.  
  391.  
  392.  
  393.           CIRCLE3 PROBLEM 2:
  394.  
  395.           In line 406 of CIRCLE.C, the reference to FlashDlgProc is meant
  396.           to pass the address of a certain type of function to the function
  397.           VBDialogBoxParam. It's function prototype on line 423 is:
  398.  
  399.            BOOL FAR PASCAL _export FlashDlgProc(HWND, USHORT, USHORT, LONG)
  400.  
  401.           but what is required for VBDialogBoxParam (on line 309 of
  402.           VBAPI.H) is the type FARPROC that is defined on line 151 of
  403.           WINDOWS.H as:
  404.  
  405.                         typedef int (FAR PASCAL * FARPROC)();
  406.  
  407.           OK, so all we need to do is cast this FARPROC type on the
  408.           function FlashDlgProc.  Change line 406 of CIRCLE.C to read:
  409.  
  410.           VBDialogBoxParam(hmodDLL, "FlashDlg", (FARPROC)FlashDlgProc, 0L);
  411.  
  412.           Now your CIRCLE3.PRJ should compile cleanly.  Remember to rename
  413.           (or copy) CIRCLE3.DLL to CIRCLE3.VBX  then fire up Visual BASIC
  414.           and try it out!
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.           Brent K. Langley  Compuserve Userid 70312,2142             Page 7
  450.  
  451.  
  452.                              Using Borland C++ IDE with 
  453.                the Microsoft Visual BASIC Control Development Kit (CDK)
  454.  
  455.  
  456.  
  457.                                          CNTR
  458.  
  459.           CNTR, the counter control uses "based pointers" in a couple of
  460.           its modules so there is some conversion that needs to be done,
  461.           but there is an error (BUG??) in CCINIT.C that we must fix first.
  462.  
  463.           In CCINIT.C on line 45, the function modifier "PASCAL"  is
  464.           missing from the definition of the function LibMain, so change
  465.           this line from:
  466.                                    BOOL FAR LibMain
  467.           To:
  468.                                BOOL FAR PASCAL LibMain
  469.  
  470.           Also, at the top of CCINIT.C (line 6, for example) remember to
  471.           place the statement:
  472.                                     #define  _CDK
  473.  
  474.  
  475.           In CNTR.H and CNTR.C we need to remove the based pointer
  476.           references and replace them with their equivalents in terms of
  477.           far pointers.  I'm not sure why Microsoft added this based
  478.           pointer complexity to this program, unless its that they felt
  479.           that it would make the code run faster (using 16 bit pointers
  480.           rather than 32 bit.)  But I don't think that this is the type of
  481.           application that would benefit from the added complication.
  482.  
  483.           In CNTR.H we have some stuff to clean up.  Lines 26 through 34
  484.           and also line 54 should be commented out as shown below:
  485.  
  486.                //   _segment  segCntr;
  487.                //   #define BP _based(segCntr) *      // based pointer
  488.                //   #define BH BP BP                  // based handle
  489.                //   typedef VOID BH BHVOID;           // void handle
  490.                //   typedef CHAR BH BHSTR;            // handle to a string
  491.  
  492.                //   #define CNTRDEREF(hctl)  ((PCNTR)(VOID *) ...
  493.  
  494.           and then change line 52 from:
  495.                               typedef  CNTR  BP  PCNTR;
  496.           to:
  497.                               typedef  CNTR far * PCNTR;
  498.  
  499.  
  500.           In CNTR.C comment-out line 53 as shown below:
  501.  
  502.                //   segCntr = (_segment) hctl;
  503.  
  504.           and change line 54 from:
  505.                                pcntr = CNTRDEREF(hctl);
  506.           to:
  507.                             pcntr = VBDerefControl(hctl);
  508.  
  509.           Now CNTR should compile ok.  Rename CNTR.DLL to CNTR.VBX an go!
  510.  
  511.  
  512.  
  513.           Brent K. Langley  Compuserve Userid 70312,2142             Page 8
  514.  
  515.  
  516.                              Using Borland C++ IDE with 
  517.                the Microsoft Visual BASIC Control Development Kit (CDK)
  518.  
  519.  
  520.  
  521.                                          PIX
  522.  
  523.           Remember to put the line:
  524.  
  525.                                      #define _CDK
  526.  
  527.           on line 6 (the blank line above #include <windows.h>) in the file
  528.           CCINIT.C as described in step 4 (above).
  529.  
  530.           Lines 81, 85, and 109 of PIX.C use the non-Borland _segment type
  531.           for casting as described for CIRCLE3 (above).  On each of these
  532.           lines modify reference in the code for
  533.  
  534.                            (_segment) hctl
  535.  
  536.           to appear like:
  537.  
  538.                          FP_SEG( hctl )
  539.  
  540.           and place the line
  541.  
  542.                            #include <dos.h>
  543.  
  544.           at the top of the file PIX.C.
  545.  
  546.           Now this control should compile and link cleanly.  Remember to
  547.           rename the resultant .DLL file to a .VBX file before you load
  548.           Visual BASIC and try it out.
  549.  
  550.           --------------------------------------------------------------
  551.  
  552.           Well, I hope this made enough sense to get you going.  I tried to
  553.           not only tell you what to do, but to also tell you where in the
  554.           various references that I found my information.  I hope it helps.
  555.  
  556.           Also, I can't emphasize enough, for you to save your programs
  557.           often.  A small mistake in your code can cause a Windows
  558.           Unexpected Application Error (UAE) and either kick you completely
  559.           out of Visual BASIC, kick you out of Windows, reboot your
  560.           machine, or freeze your machine.  I have encountered all of these
  561.           battle scars, but I survived and you will too!  Have fun....Brent
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.           Brent K. Langley  Compuserve Userid 70312,2142             Page 9
  578.